package com.ccrfid.rmc6.resource.business.prison.rollcall;

import com.ccrfid.rmc6.appconfig.exception.pojo.AppException;
import com.ccrfid.rmc6.appconfig.exception.pojo.CustomErrors;
import com.ccrfid.rmc6.entity.business.prison.rollcall.PrisonRollcallPlaceEntity;
import com.ccrfid.rmc6.pojo.Constants;
import com.ccrfid.rmc6.pojo.dto.prison.patrolcheck.PatrolCheckDataDto;
import com.ccrfid.rmc6.pojo.dto.prison.patrolcheck.PatrolCheckResultDto;
import com.ccrfid.rmc6.pojo.dto.prison.rollcall.*;
import com.ccrfid.rmc6.service.business.prison.patrolcheck.PatrolCheckService;
import com.ccrfid.rmc6.service.business.prison.rollcall.PrisonRollcallPlaceService;
import com.ccrfid.rmc6.service.business.prison.rollcall.PrisonRollcallService;
import com.ccrfid.rmc6.service.personnel.PersonnelService;
import com.ccrfid.rmc6.service.sys.KeyValueService;
import com.ccrfid.rmc6.util.JsonUtil;
import com.fasterxml.jackson.databind.JsonNode;
import net.coobird.thumbnailator.Thumbnails;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.activation.MimetypesFileTypeMap;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;

@Path("prison-rollcall")
@Produces(MediaType.APPLICATION_JSON)
public class SyncHandsetDataResource {
    private static final Logger logger = LoggerFactory.getLogger(SyncHandsetDataResource.class);

    @Autowired
    private PrisonRollcallService rollcallService;
    @Autowired
    private PrisonRollcallPlaceService rollcallPlaceService;
    @Autowired
    private PersonnelService personnelService;
    @Autowired
    private KeyValueService keyValueService;
    @Autowired
    private PatrolCheckService patrolCheckService;

    @GET
    @Path("app-version")
    public String getHandsetAppVersion() {
        return keyValueService.getHandsetAppVersion();
    }

    @POST
    @Path("app-upload")
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public Boolean uploadHandsetAppFile(@FormDataParam("file") final InputStream inputStream,
                                        @FormDataParam("file") final FormDataContentDisposition fd,
                                        @FormDataParam("version") final String version) throws IOException {
        String fileName = new String(fd.getFileName().getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
        keyValueService.uploadHandsetAppFile(version, fileName, inputStream);
        return true;
    }

    @GET
    @Path("app-download")
    public Response downloadHandsetAppFile() throws AppException {
        File file = keyValueService.downloadHandsetAppFile();
        String mediaType = new MimetypesFileTypeMap().getContentType(file);
        String fileName = new String(file.getName().getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);

        return Response.ok(file, mediaType)
                .header("Content-disposition", "attachment;filename=" + fileName)
                .header("Cache-Control", "no-cache")
                .header("Transfer-File-Size", file.length())
                .build();
    }

    @POST
    @Path("data")
    @Consumes(MediaType.APPLICATION_JSON)
    public RespEntity<?> syncData(ReqEntity req) throws AppException {
        if (req.getMethod().equals("get")) {
            //get：获取点名配置数据
            return new RespEntity<>(req.getMethod(), getData());
        } else if (req.getMethod().equals("post")) {
            //post：保存点名结果
            List<PrisonRollcallResultDto> list = getPrisonRollcallResultDtoList(req.getData());
            if (list != null && list.size() > 0) {
                for (PrisonRollcallResultDto dto : list) {
                    rollcallService.uploadRollcallResult(dto);
                }
                return new RespEntity<>(req.getMethod(), true);
            } else {
                throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                        CustomErrors.param_is_null.getCode(), CustomErrors.param_is_null.getReason(), "");
            }
        } else if (req.getMethod().equals("get-photo")) {
            Long personnelId = JsonUtil.INSTANCE.treeToValue(req.getData(), Long.class);
            if (personnelId != null) {
                byte[] data = personnelService.getPersonnelPhoto(personnelId);
                if (data != null) {
                    //压缩
                    try {
                        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                        Thumbnails.of(new ByteArrayInputStream(data))
                                .size(270, 330)
                                .toOutputStream(outputStream);
                        //返回base64
                        String base64Str = new String(Base64.getEncoder().encode(outputStream.toByteArray()));
                        return new RespEntity<>(req.getMethod(), personnelId, base64Str);
                    } catch (IOException ex) {
                        return new RespEntity<>(req.getMethod(), personnelId, null);
                    }
                } else {
                    return new RespEntity<>(req.getMethod(), personnelId, null);
                }
            } else {
                throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                        CustomErrors.param_is_null.getCode(), CustomErrors.param_is_null.getReason(), "");
            }
        } else if (req.getMethod().equals("get-patrol-check-config")) {
            //获取巡更配置
            return new RespEntity<>(req.getMethod(), getPatrolCheckDataConfig());

        } else if (req.getMethod().equals("post-patrol-check-data")) {
            //提交巡更结果
            List<PatrolCheckResultDto> list = getPatrolCheckResultDtoList(req.getData());
            if (list != null && list.size() > 0) {

                updatePatrolCheckResultList(list);

                return new RespEntity<>(req.getMethod(), true);
            } else {
                throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                        CustomErrors.param_is_null.getCode(), CustomErrors.param_is_null.getReason(), "");
            }
        } else {
            //其他：不支持
            return new RespEntity<>(req.getMethod(), "method: " + req.getMethod() + ", not support!");
        }
    }

    private PrisonRollcallDataDto getData() {
        List<PrisonRollcallPlaceDto> placeInfoList = new ArrayList<>();

        List<PrisonRollcallPlaceEntity> placeList = rollcallPlaceService.getRollcallPlaceList();
        for (PrisonRollcallPlaceEntity placeEntity : placeList) {
            PrisonRollcallPlaceDto placeInfo = new PrisonRollcallPlaceDto();
            placeInfo.setPlace(placeEntity);
            if (placeEntity.getNodeType().equals(Constants.NODE_TYPE.CATALOG.id)) {
                placeInfo.setRollcallPersonnelList(null);
            } else {
                placeInfo.setRollcallPersonnelList(rollcallPlaceService.getRollcallPlacePersonnelList(placeEntity.getId()));
            }
            placeInfoList.add(placeInfo);
        }

        PrisonRollcallDataDto dataDto = new PrisonRollcallDataDto();
        dataDto.setTimeList(rollcallService.getRollcallTaskTimeList());
        dataDto.setPolicemanList(rollcallService.getRollcallPolicemanList());
        dataDto.setPlaceInfoList(placeInfoList);

        return dataDto;
    }

    private PrisonRollcallResultDto getPrisonRollcallResultDto(JsonNode jsonNode) {
        PrisonRollcallResultDto resultDto = JsonUtil.INSTANCE.treeToValue(jsonNode, PrisonRollcallResultDto.class);
        return resultDto;
    }

    private List<PrisonRollcallResultDto> getPrisonRollcallResultDtoList(JsonNode jsonNode) {
        PrisonRollcallResultDto[] list =
                JsonUtil.INSTANCE.treeToValue(jsonNode, PrisonRollcallResultDto[].class);
        if (list != null) {
            return Arrays.asList(list);
        } else {
            return null;
        }
    }

    private PatrolCheckDataDto getPatrolCheckDataConfig() {
        PatrolCheckDataDto dataDto = new PatrolCheckDataDto();

        dataDto.setTimeList(patrolCheckService.getPatrolCheckPlanTimeList());
        dataDto.setCheckGroupList(patrolCheckService.getPatrolCheckGroupConfig());
        dataDto.setPolicemanList(rollcallService.getRollcallPolicemanList());

        return dataDto;
    }

    private List<PatrolCheckResultDto> getPatrolCheckResultDtoList(JsonNode jsonNode) {
        PatrolCheckResultDto[] list = JsonUtil.INSTANCE.treeToValue(jsonNode, PatrolCheckResultDto[].class);
        if (list != null) {
            return Arrays.asList(list);
        } else {
            return null;
        }
    }

    private void updatePatrolCheckResultList(List<PatrolCheckResultDto> resultList) {
        patrolCheckService.updatePatrolCheckResultList(resultList);
    }
}
